﻿using System;
using System.Text;
using System.Collections.Generic;
using Ex03.GarageLogic;

namespace Ex03.GarageManagementSystem.ConsoleUI
{
    /// <summary>
    /// This class will deal with the user interface
    /// </summary>
    public class UserInterface
    {
        private const string k_SystemGoodbyeMessage = "Thanks for using Garage management system";
        private Garage m_Garage = new Garage();

        /// <summary>
        /// A constructor for the User Interface class
        /// </summary>
        public UserInterface()
        {
        }

        private Garage Garage
        {
            get { return m_Garage; }
        }

        /// <summary>
        /// This is the main program method. The method will run in a loop
        /// until the user decides to exit the program
        /// </summary>
        public void StartGarageManagmentSystem()
        {
            MenuGenerator.eMenuOptions choice;
            do
            {
                choice = MenuGenerator.PresentMainMenuAndGetUserChoice();
                switch (choice)
                {
                    case MenuGenerator.eMenuOptions.InsertVehicleToGarage:
                        insertVehicleToGarageCase();
                        break;
                    case MenuGenerator.eMenuOptions.ShowVehiclesInGarage:
                        ShowVehiclesInGarageCase();
                        break;
                    case MenuGenerator.eMenuOptions.ShowVehiclesInGarageByStatus:
                        showVehiclesInGarageByStatusCase();
                        break;
                    case MenuGenerator.eMenuOptions.ChangeVehicleStatusInGarage:
                        changeVehicleStatusInGarageCase();
                        break;
                    case MenuGenerator.eMenuOptions.FullyInflateVehicleWheels:
                        fullyInflateVehicleWheelsCase();
                        break;
                    case MenuGenerator.eMenuOptions.RefuelVehicle:
                        refuelVehicleCase();
                        break;
                    case MenuGenerator.eMenuOptions.ChargeVehicle:
                        chargeVehicleCase();
                        break;
                    case MenuGenerator.eMenuOptions.ShowVehicleDetails:
                        showVehicleDetailsCase();
                        break;
                    default:
                        // should only be Exit option
                        Console.Write(k_SystemGoodbyeMessage);
                        break;
                }
            } while (choice != MenuGenerator.eMenuOptions.Exit);
        }

        private GarageClient createGarageClientWithVehicle()
        {
            string formStringAnswer;
            GarageClient garageClient = createNewGarageClient();
            VehiclesConstructor.eVehicleTypeSupported vehicleType = MenuGenerator.PresentVehicleTypeMenuAndGetUserChoice();
            string plateNumber = promptUserForPlateNumber();
            Vehicle vehicle = VehiclesConstructor.Instance.createVehicleByType(vehicleType, plateNumber);
            Dictionary<string, string> vehicleForm = vehicle.GetForm();
            Dictionary<string, string> vehicleFormAnswered = new Dictionary<string, string>();

            foreach (KeyValuePair<string, string> pair in vehicleForm)
            {
                Console.Write(string.Format("{0} : ", pair.Key));
                formStringAnswer = Console.ReadLine();
                vehicleFormAnswered.Add(pair.Key, formStringAnswer);
            }

            vehicle.Initialize(vehicleFormAnswered);
            garageClient.Vehicle = vehicle;

            return garageClient;
        }

        private GarageClient createNewGarageClient()
        {
            string clientName;
            string clientPhone;

            Console.Write("Enter client name: ");
            clientName = Console.ReadLine();
            Console.Write("Enter client phone number: ");
            clientPhone = Console.ReadLine();

            return new GarageClient(clientName, clientPhone);
        }

        private VehiclesConstructor.eVehicleTypeSupported promptUserForVehicleType()
        {
            int numberChosen;
            VehiclesConstructor.eVehicleTypeSupported typeChosen;
            int numberOfVehicleOptions = Enum.GetValues(typeof(VehiclesConstructor.eVehicleTypeSupported)).Length;

            do
            {
                Console.WriteLine(string.Format("Choose your vehicle type ({0}-{1})", 1, numberOfVehicleOptions));
                foreach (VehiclesConstructor.eVehicleTypeSupported VehicleType in Enum.GetValues(typeof(VehiclesConstructor.eVehicleTypeSupported)))
                {
                    Console.WriteLine(string.Format("{0}. {1}", ((int)VehicleType), Enum.GetName(typeof(VehiclesConstructor.eVehicleTypeSupported), (int)VehicleType)));
                }

                numberChosen = int.Parse(Console.ReadLine());
            } while ((numberChosen < 1) || (numberChosen > numberOfVehicleOptions));

            return typeChosen = (VehiclesConstructor.eVehicleTypeSupported)Enum.Parse(typeof(VehiclesConstructor.eVehicleTypeSupported), numberChosen.ToString());
        }

        private string promptUserForPlateNumber()
        {
            string plateNumberString;

            do
            {
                Console.Write("Enter your vehicle's plate number: ");
                plateNumberString = Console.ReadLine();
            } while (!Vehicle.IsValidPlateNumber(plateNumberString));

            return plateNumberString;
        }

        private void PresentItemsInStringList(List<string> i_StringList)
        {
            StringBuilder stringBuilder = new StringBuilder();

            if (i_StringList.Count == 0)
            {
                stringBuilder.AppendLine("No Vehicles where found");
            }

            foreach (string stringItem in i_StringList)
            {
                stringBuilder.AppendLine(stringItem);
            }

            Console.Write(stringBuilder.ToString());
        }

        private void insertVehicleToGarageCase()
        {
            try
            {
                GarageClient newGarageClient = createGarageClientWithVehicle();
                Garage.AddNewGarageClient(newGarageClient);
                Console.WriteLine("Vehicle was added successfully");
            }
            catch (Exception)
            {
                Console.WriteLine("Vehicle was NOT added successfully - try again!");
            }
            finally
            {
                System.Console.ReadKey();
            }
        }

        private void refuelVehicleCase()
        {
            try
            {
                float amountToFillInLitres;
                bool parsedOK;
                List<string> plateNumberOfVehiclesInGarage = Garage.GetVehiclesPlateNumberCurrentlyInGarage();
                if (plateNumberOfVehiclesInGarage.Count != 0)
                {
                    string clientVehiclePlateNumber = MenuGenerator.PresentVehiclesPlateNumberAndGetUserChoice(plateNumberOfVehiclesInGarage);
                    FuelPoweredVehicle.eFuelType fuelType = MenuGenerator.PresentFuelTypeMenuAndGetUserChoice();
                    do
                    {
                        Console.Write("Enter amount of fuel to add: ");
                        parsedOK = float.TryParse(Console.ReadLine(), out amountToFillInLitres);
                    } while (!parsedOK);

                    Garage.RefuelFuelPoweredVehicle(clientVehiclePlateNumber, fuelType, amountToFillInLitres);
                    Console.WriteLine("Your vehicle was successfully refueled!");
                }
                else
                {
                    Console.WriteLine("Currently there are no vehicles in garage to refuel");
                }
            }
            catch (Exception)
            {
                Console.WriteLine("Vehicle was not refueled correctly - try again!");
            }
            finally
            {
                System.Console.ReadKey();
            }
        }

        private void chargeVehicleCase()
        {
            try
            {
                float amountOfMinutesToCharge;
                bool parsedOK;
                List<string> plateNumberOfVehiclesInGarage = Garage.GetVehiclesPlateNumberCurrentlyInGarage();
                if (plateNumberOfVehiclesInGarage.Count != 0)
                {
                    string clientVehiclePlateNumber = MenuGenerator.PresentVehiclesPlateNumberAndGetUserChoice(plateNumberOfVehiclesInGarage);
                    do
                    {
                        Console.Write("Enter number of minutes to charge: ");
                        parsedOK = float.TryParse(Console.ReadLine(), out amountOfMinutesToCharge);
                    } while (!parsedOK);

                    Garage.ChargeElerctricPoweredVehicle(clientVehiclePlateNumber, amountOfMinutesToCharge);
                    Console.WriteLine("Your vehicle was successfully charged!");

                }
                else
                {
                    Console.WriteLine("Currently there are no vehicles in garage to charge");
                }
            }
            catch (Exception)
            {
                Console.WriteLine("Vehicle was not refueled correctly - try again!");
            }
            finally
            {
                System.Console.ReadKey();
            }
        }

        private void fullyInflateVehicleWheelsCase()
        {
            try
            {
                List<string> plateNumberOfVehiclesInGarage = Garage.GetVehiclesPlateNumberCurrentlyInGarage();
                if (plateNumberOfVehiclesInGarage.Count != 0)
                {
                    string clientVehiclePlateNumber = MenuGenerator.PresentVehiclesPlateNumberAndGetUserChoice(plateNumberOfVehiclesInGarage);
                    Garage.FullyInflateAllTiresOfVehicle(clientVehiclePlateNumber);
                    Console.WriteLine("Vehicle's tires were successfully inflated!");
                }
                else
                {
                    Console.WriteLine("Currently there are no vehicles in garage to inflate their tires");
                }
            }
            catch (Exception)
            {
                Console.WriteLine("Vehicle's wheels were NOT inflated - try again!");
            }
            finally
            {
                System.Console.ReadKey();
            }
        }

        private void changeVehicleStatusInGarageCase()
        {
            try
            {
                List<string> plateNumberOfVehiclesInGarage = Garage.GetVehiclesPlateNumberCurrentlyInGarage();
                if (plateNumberOfVehiclesInGarage.Count != 0)
                {
                    string clientVehiclePlateNumber = MenuGenerator.PresentVehiclesPlateNumberAndGetUserChoice(plateNumberOfVehiclesInGarage);
                    GarageClient.eProcessStatus NewProcessStatus = MenuGenerator.PresentProcessStatusMenuAndGetUserChoice("Choose your vehicle's new process status");
                    Garage.ChangeGarageClientStatus(clientVehiclePlateNumber, NewProcessStatus);
                    Console.WriteLine("Vehicle's process status was successfully changed!");
                }
                else
                {
                    Console.WriteLine("Currently there are no vehicles in garage to change their status");
                }
            }
            catch (Exception)
            {
                Console.WriteLine("Vehicle's status was NOT changed - try again!");
            }
            finally
            {
                System.Console.ReadKey();
            }
        }

        private void showVehiclesInGarageByStatusCase()
        {
            GarageClient.eProcessStatus processStatus = MenuGenerator.PresentProcessStatusMenuAndGetUserChoice("Choose vehicles process status filter");
            List<string> plateNumberOfVehiclesInGarage = Garage.GetVehiclesPlateNumberCurrentlyInGarageByPorcessStatus(processStatus);
            PresentItemsInStringList(plateNumberOfVehiclesInGarage);
            System.Console.ReadKey();
        }

        private void ShowVehiclesInGarageCase()
        {
            List<string> plateNumberOfVehiclesInGarage = Garage.GetVehiclesPlateNumberCurrentlyInGarage();
            PresentItemsInStringList(plateNumberOfVehiclesInGarage);
            System.Console.ReadKey();
        }

        private void showVehicleDetailsCase()
        {
            List<string> plateNumberOfVehiclesInGarage = Garage.GetVehiclesPlateNumberCurrentlyInGarage();
            if (plateNumberOfVehiclesInGarage.Count != 0)
            {
                string clientVehiclePlateNumber = MenuGenerator.PresentVehiclesPlateNumberAndGetUserChoice(plateNumberOfVehiclesInGarage);
                Console.WriteLine(Garage.GettFullClientAndVehicleDetails(clientVehiclePlateNumber));
            }
            else
            {
                Console.WriteLine("Currently there are no vehicles in garage to present");
            }

            System.Console.ReadKey();
        }
    }
}
